home *** CD-ROM | disk | FTP | other *** search
- // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
- // see COPYRIGHT for reuse legalities
- //
-
- #import "RIBRotate.h"
-
- @implementation RIBRotate
-
- + initialize { return [RIBRotate setVersion:1], self; }
-
- - updateMatrix
- {
- double theta;
- double alphaHat, versineOfAlphaHat;
- RtPoint aHat;
- RtFloat divisor;
-
-
- N3D_CopyMatrix(N3DIdentityMatrix, myMatrix);
- theta = toRadians(angle);
- alphaHat = theta;
-
- // three simple cases are rotation about x, y, or z
- if ((dx == 1.0) && (dy == 0.0) && (dz == 0.0)) // X
- { myMatrix[1][1] = (RtFloat)cos(theta);
- myMatrix[1][2] = (RtFloat)sin(theta);
- myMatrix[2][1] = -1. * (RtFloat)sin(theta);
- myMatrix[2][2] = (RtFloat)cos(theta);
- return self;
- }
- if ((dx == 0.0) && (dy == 1.0) && (dz == 0.0)) // Y
- { myMatrix[0][0] = (RtFloat)cos(theta);
- myMatrix[0][2] = -1. * (RtFloat)sin(theta);
- myMatrix[2][0] = (RtFloat)sin(theta);
- myMatrix[2][2] = (RtFloat)cos(theta);
- return self;
- }
- if ((dx == 0.0) && (dy == 0.0) && (dz == 1.0)) // Z
- { myMatrix[0][0] = (RtFloat)cos(theta);
- myMatrix[0][1] = (RtFloat)sin(theta);
- myMatrix[1][0] = -1. * (RtFloat)sin(theta);
- myMatrix[1][1] = (RtFloat)cos(theta);
- return self;
- }
-
- // yuck. we now have to do rotation about an arbitrary axis. oh joy.
-
- divisor = (RtFloat)(sqrt((dx * dx) + (dy * dy) + (dz * dz)));
- aHat[0] = dx/divisor;
- aHat[1] = dy/divisor;
- aHat[2] = dz/divisor;
- versineOfAlphaHat = 1 - cos(alphaHat);
-
- myMatrix[0][0] = 1 + (((aHat[0] * aHat[0]) - 1) * versineOfAlphaHat);
- myMatrix[0][1] = (aHat[2] * sin(alphaHat)) + (aHat[0] * aHat[1] * versineOfAlphaHat);
- myMatrix[0][2] = (-1 * aHat[1] * sin(alphaHat)) + (aHat[2] * aHat[0] * versineOfAlphaHat);
- myMatrix[1][0] = (-1 * aHat[2] * sin(alphaHat)) + (aHat[0] * aHat[1] * versineOfAlphaHat);
- myMatrix[1][1] = 1 + (((aHat[1] * aHat[1]) - 1) * versineOfAlphaHat);
- myMatrix[1][2] = (aHat[0] * sin(alphaHat)) + (aHat[1] * aHat[0] * versineOfAlphaHat);
- myMatrix[2][0] = (aHat[1] * sin(alphaHat)) + (aHat[2] * aHat[0] * versineOfAlphaHat);
- myMatrix[2][1] = (-1 * aHat[0] * sin(alphaHat)) + (aHat[1] * aHat[0] * versineOfAlphaHat);
- myMatrix[2][2] = 1 + (((aHat[2] * aHat[2]) - 1) * versineOfAlphaHat);
-
- //NXLogError("RIBRotate (-updateMatrix):\n");
- //NXLogError("\t%f %f %f %f\n", myMatrix[0][0], myMatrix[0][1], myMatrix[0][2], myMatrix[0][3]);
- //NXLogError("\t%f %f %f %f\n", myMatrix[1][0], myMatrix[1][1], myMatrix[1][2], myMatrix[1][3]);
- //NXLogError("\t%f %f %f %f\n", myMatrix[2][0], myMatrix[2][1], myMatrix[2][2], myMatrix[2][3]);
- //NXLogError("\t%f %f %f %f\n", myMatrix[3][0], myMatrix[3][1], myMatrix[3][2], myMatrix[3][3]);
-
- return self;
- }
-
- - init
- {
- [super init];
- angle = 90.0;
- dx = 1.0;
- dy = 0.0;
- dz = 0.0;
-
- [self updateMatrix];
-
- return self;
- }
-
- - awake
- {
- [super awake];
- [self updateMatrix];
-
- return self;
- }
-
- - setAngle:(RtFloat)newAngle dx:(RtFloat)newDX dy:(RtFloat)newDY dz:(RtFloat)newDZ
- {
- angle = newAngle;
- dx = newDX;
- dy = newDY;
- dz = newDZ;
- [self updateMatrix];
-
- return self;
- }
-
- - (BOOL)isLerpable { return YES; }
-
- // note: because we've made the WWSampleList "safe" for having
- // multiple samples with the same data, it's perfectly valid to return
- // yourself or b
- - lerpWith:b by:(float)uValue
- {
- id newMe = nil;
- RtFloat angleA, dxA, dyA, dzA;
- RtFloat angleB, dxB, dyB, dzB;
-
- if (([self class] != [b class]) || (uValue <= 0.0))
- { return self;
- }
-
- if (uValue >= 1.0)
- { return b;
- }
-
- newMe = [super lerpWith:b by:uValue]; // this makes a copy for us
-
- // okay, now do the specific stuff for this class
- [self getAngle:&angleA dx:&dxA dy:&dyA dz:&dzA];
- [b getAngle:&angleB dx:&dxB dy:&dyB dz:&dzB];
- [newMe setAngle:(angleA + ((angleB - angleA) * uValue))
- dx:(dxA + ((dxB - dxA) * uValue))
- dy:(dyA + ((dyB - dyA) * uValue))
- dz:(dzA + ((dzB - dzA) * uValue))];
-
- return newMe;
- }
-
-
- - lerpSelfWith:b by:(float)uValue
- {
- RtFloat angleA, dxA, dyA, dzA;
- RtFloat angleB, dxB, dyB, dzB;
-
- if (([self class] != [b class]) || (uValue <= 0.0))
- { return self;
- }
-
- if (uValue >= 1.0)
- { return b;
- }
-
- [super lerpSelfWith:b by:uValue]; // this makes a copy for us
-
- // okay, now do the specific stuff for this class
- [self getAngle:&angleA dx:&dxA dy:&dyA dz:&dzA];
- [b getAngle:&angleB dx:&dxB dy:&dyB dz:&dzB];
- [self setAngle:(angleA + ((angleB - angleA) * uValue))
- dx:(dxA + ((dxB - dxA) * uValue))
- dy:(dyA + ((dyB - dyA) * uValue))
- dz:(dzA + ((dzB - dzA) * uValue))];
-
- return self;
- }
-
-
- - (BOOL)isMoot
- {
- if (!angle) { return YES; }
- return NO;
- }
-
- - (BOOL)theSameAs:otherRIBCommand
- {
- RtFloat theAngle, theDX, theDY, theDZ;
-
-
- [otherRIBCommand getAngle:&theAngle dx:&theDX dy:&theDY dz:&theDZ];
- if (angle != theAngle)
- { return NO;
- }
- if (dx != theDX)
- { return NO;
- }
- if (dy != theDY)
- { return NO;
- }
- if (dz != theDZ)
- { return NO;
- }
-
- return [super theSameAs:otherRIBCommand];
- }
-
- - setDX:(RtFloat)newDX dy:(RtFloat)newDY dz:(RtFloat)newDZ
- {
- dx = newDX;
- dy = newDY;
- dz = newDZ;
-
- N3D_CopyMatrix(N3DIdentityMatrix, myMatrix);
- myMatrix[3][0] = dx;
- myMatrix[3][1] = dy;
- myMatrix[3][2] = dz;
-
- return self;
- }
-
- - getAngle:(RtFloat *)anglePtr dx:(RtFloat *)dxPtr dy:(RtFloat *)dyPtr dz:(RtFloat *)dzPtr
- {
- *anglePtr = angle;
- *dxPtr = dx;
- *dyPtr = dy;
- *dzPtr = dz;
-
- return self;
- }
-
- - renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- RiRotate(angle, dx, dy, dz);
-
- return self;
- }
-
- - transformCTM:(WW3DAttributeState *)attributeState startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
- {
- RtMatrix aMatrix, tmpMatrix;
-
-
- [attributeState getTransformMatrix:aMatrix];
- N3DMultiplyMatrix(myMatrix, aMatrix, tmpMatrix);
- [attributeState setTransformMatrix:tmpMatrix];
-
- //NXLogError("RIBRotate myMatrix (-transformCTM:startingAt:endingAt):\n");
- //NXLogError("\t%f %f %f %f\n", myMatrix[0][0], myMatrix[0][1], myMatrix[0][2], myMatrix[0][3]);
- //NXLogError("\t%f %f %f %f\n", myMatrix[1][0], myMatrix[1][1], myMatrix[1][2], myMatrix[1][3]);
- //NXLogError("\t%f %f %f %f\n", myMatrix[2][0], myMatrix[2][1], myMatrix[2][2], myMatrix[2][3]);
- //NXLogError("\t%f %f %f %f\n", myMatrix[3][0], myMatrix[3][1], myMatrix[3][2], myMatrix[3][3]);
- //NXLogError("RIBRotate aMatrix (-transformCTM:startingAt:endingAt):\n");
- //NXLogError("\t%f %f %f %f\n", aMatrix[0][0], aMatrix[0][1], aMatrix[0][2], aMatrix[0][3]);
- //NXLogError("\t%f %f %f %f\n", aMatrix[1][0], aMatrix[1][1], aMatrix[1][2], aMatrix[1][3]);
- //NXLogError("\t%f %f %f %f\n", aMatrix[2][0], aMatrix[2][1], aMatrix[2][2], aMatrix[2][3]);
- //NXLogError("\t%f %f %f %f\n", aMatrix[3][0], aMatrix[3][1], aMatrix[3][2], aMatrix[3][3]);
-
- return self;
- }
-
- - (BOOL)isMotionBlurrable { return YES; }
-
- - writeEve:(NXStream *)stream atTabLevel:(int)tab
- {
- int i;
-
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "Rotate %f %f %f %f;", angle, dx, dy, dz);
- return self;
- }
-
- - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
- {
- int i;
-
-
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "Rotation {\n");
- for (i = 0; i < (tab+1); i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "rotation %f %f %f %f\n", dx, dy, dz, angle);
- for (i = 0; i < tab; i++)
- { NXPrintf(stream, "\t");
- }
- NXPrintf(stream, "}");
-
- return self;
-
- }
- #define typeVector "ffff"
- #define typeValues &angle, &dx, &dy, &dz
-
- - read:(NXTypedStream*)stream
- {
- int version;
- [super read:stream];
-
- NX_DURING
- version = NXTypedStreamClassVersion(stream,"RIBRotate");
- if (version == 0) NXReadTypes(stream,"i",&version), version=1;
- if (version == 1)
- { NXReadTypes(stream,typeVector,typeValues);
- }
- NX_HANDLER
- NXLogError("in read: %s, exception [%d] raised.\n",
- [[self class] name], NXLocalHandler.code);
- return nil;
- NX_ENDHANDLER
- return self;
- }
-
- - write:(NXTypedStream*)stream
- {
- [super write:stream];
-
- NXWriteTypes(stream,typeVector, typeValues);
-
- return self;
- }
-
- @end
-